package com.springboot.auth.authorization.oauth2.enhancer;

import com.springboot.auth.authorization.model.vo.Authcode;
import com.springboot.auth.authorization.service.ISlidingCodeService;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by ZengJian on 2021/2/3 0003 上午 9:22
 */
public class CustomTokenGranter extends ResourceOwnerPasswordTokenGranter {
    private static final String GRANT_TYPE = "custom";

    private final ISlidingCodeService slidingCodeService;

    private final AuthenticationManager authenticationManager;

    public CustomTokenGranter(AuthenticationManager authenticationManager,
                              AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
                              OAuth2RequestFactory requestFactory, ISlidingCodeService slidingCodeService) {
        super(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.authenticationManager = authenticationManager;
        this.slidingCodeService = slidingCodeService;
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
        String username = parameters.get("username");
        String password = parameters.get("password");
        String captchaVerification = parameters.get("slidingCode");


//        authcodeProvider.getAuthcode(captchaVerification);
//        System.out.println("authcodeProvider:"+authcodeProvider.getAuthcode(captchaVerification));
        Authcode authcode = new Authcode();
        authcode.setCaptchaVerification(captchaVerification);
        String code = slidingCodeService.sliding(authcode);
        if (code.equals("6111")) {
            throw new InvalidGrantException("验证失败");
        } else if (code.equals("6110")) {
            throw new InvalidGrantException("验证码已失效，请重新获取");
        } else if (!code.equals("0000")) {
            throw new InvalidGrantException("验证码错误");
        }
//        System.out.println("captchaVerification:"+authcode.getCaptchaVerification()+":codes:"+ slidingCodeService.sliding(authcode));
        Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password);
        CustomAuthenticationToken customAuthenticationToken = new CustomAuthenticationToken(userAuth);
        ((AbstractAuthenticationToken) userAuth).setDetails(parameters);
        try {
            userAuth = this.authenticationManager.authenticate(customAuthenticationToken);
        } catch (AccountStatusException ase) {

            throw new InvalidGrantException(ase.getMessage());
        } catch (BadCredentialsException e) {

            throw new InvalidGrantException(e.getMessage());
        }
        if (userAuth == null || !userAuth.isAuthenticated()) {
            throw new InvalidGrantException("Could not authenticate user: " + username);
        }

        OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        return new OAuth2Authentication(storedOAuth2Request, customAuthenticationToken);
    }
}
